﻿using System;
using System.Collections.Generic;
using System.Linq;
using SystemX.Infrastructure;
using System.Linq.Dynamic;

namespace SystemX.Web.Infrastructure
{
	/// <summary>
	/// Server side Data for JQuery's Flexigrid plugin v1.03b
	/// </summary>
	/// <remarks>
	/// http://webplicity.net/flexigrid/
	/// </remarks>
	[Serializable]
	public class FlexigridData<T>
	{
		public FlexigridData() { }
		public FlexigridData(IEnumerable<T> data, FlexiGridInputData param):this(data,param,false){ }
		public FlexigridData(IEnumerable<T> data, FlexiGridInputData param,bool _includeBaseFields)
		{
			ExtraData = new Dictionary<string, object>();
			items = data;
			Params = param;
			includeBaseFields = _includeBaseFields;
			Resolve();
		}
		
		
		#region member variables
		private bool includeBaseFields;
		private IEnumerable<T> items;
		private FlexiGridInputData Params;
		/// <summary>
		/// Current page
		/// </summary>
		public int page { get; set; }
		/// <summary>
		/// Total record number
		/// </summary>
		public int total { get; set; }
		/// <summary>
		/// Rows
		/// </summary>
		public List<FlexigridDataRow<T>> rows { get; set; }
		/// <summary>
		/// Custom extra data
		/// </summary>
		public Dictionary<string, object> ExtraData { get; set; }
		#endregion

		#region biz methods
		/// <summary>
		/// Add a datarow
		/// </summary>
		/// <param name="row"></param>
		public void AddDataRow(FlexigridDataRow<T> row)
		{
			row.OnFillCells();
			this.rows.Add(row);
		}
		#endregion

		#region Helper methods

		void Resolve() {
			var items1 = items.AsQueryable();
			//where
			if (!string.IsNullOrEmpty(Params.query))
			{
				items1 = items1.Where(x => x.GetPropertyValue(Params.qtype).ToString().ToUpper().Contains(Params.query.ToUpper()));
			};
			//total records
			var total1 = items1.Count();
			//paged records
			items1 = items1
			.Skip((Params.page - 1) * Params.rp)
			.Take(Params.rp);
			//order
			items1 = items1.OrderBy(String.Format("{0} {1}", Params.sortname, Params.sortorder));
			//prepare flexigrid's data
			page = Params.page;
			total = total1;
			rows = new List<FlexigridDataRow<T>>();

			FlexigridDataRow<T> flexigridrow = null;
			object id = null;
			items1.ToList().ForEach(x =>
			{
				id = x.GetPropertyValue(typeof(FlexigridKeyAttribute));
				id = id ?? DateTime.Now.Ticks;
				flexigridrow = new FlexigridDataRow<T>(id.ToString(), x);
				flexigridrow.FillCells += flexigridrow_FillCells;
				AddDataRow(flexigridrow);
			});
		}
		void flexigridrow_FillCells(object sender, FlexigridEventArgs<T> e)
		{
			var row = sender as FlexigridDataRow<T>;
			if (row != null)
			{
				row.cell = FlexigridFieldAttribute.GetFlexigridFieldValues<T>(e.DataRowItem, includeBaseFields);
			}
		}
		#endregion
	}
	/// <summary>
	/// DataRow for JQuery's Flexigrid plugin
	/// </summary>
	/// <typeparam name="T">Datarow's data type.Category,eg.</typeparam>
	[Serializable]
	public class FlexigridDataRow<T>{
		private T tempDataRowObj;
		private string _id;
		/// <summary>
		/// DataRow's datakey
		/// </summary>
		public string id {
			get { return _id; }
			set { _id = value; }
		}
		private object[] _cell;
		/// <summary>
		/// DataRow's cell values
		/// </summary>
		public object[] cell {
			get {
				return _cell;
			}
			set { _cell = value; }
		}

		public FlexigridDataRow(string key,T obj){
			_id = key;
			_cell = new object[]{ };
			tempDataRowObj = obj;
		}
		#region Events
		/// <summary>
		/// FillCells Event handler
		/// </summary>
		public event EventHandler<FlexigridEventArgs<T>> FillCells;
		/// <summary>
		/// Accurs when filling cells
		/// </summary>
		public void OnFillCells() {
			if (FillCells != null) {
				FlexigridEventArgs<T> args = new FlexigridEventArgs<T>();
				args.DataRowItem = this.tempDataRowObj;
				FillCells(this, args);
			}
		}
		#endregion
	}
}
